using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Threading;
public class Image 
{
    const int INTERVAL = 5;
    const int MAXTIME = 500;

    public Texture2D texture = new Texture2D(1, 1);
    public static Image imgTemp;
    public static string filenametemp;
    public static byte[] datatemp;
    public static Image imgSrcTemp;
    public static int xtemp, ytemp, wtemp, htemp, transformtemp;
    public int w, h;
    public static int status;
    // 0:free 
    // 1:working 
    // 2:waitingCreateEmptyImage 
    // 3:waitingCreateImageFromFileName
    // 4:waitingCreateImageFromArray
    // 5:waitingCreateImageFromPartImage
    public static Image createEmptyImage()
    {
        return __createEmptyImage();
        if (Thread.CurrentThread.Name == Main.mainThreadName)
            return __createEmptyImage();
        else
            return _createEmptyImage();
    }
    public static Image createImage(string filename)
    {
        return __createImage(filename);
        if (Thread.CurrentThread.Name == Main.mainThreadName)
            return __createImage(filename);
        else
            return _createImage(filename);
    }
    public static Image createImage(byte[] imageData)
    {
        return __createImage(imageData);
        if (Thread.CurrentThread.Name == Main.mainThreadName)
            return __createImage(imageData);
        else
            return _createImage(imageData);
    }

    public static Image createImage(Image src, int x, int y, int w, int h, int transform)
    {
        return __createImage(src, x, y, w, h, transform);
        if (Thread.CurrentThread.Name == Main.mainThreadName)
            return __createImage(src, x, y, w, h, transform);
        else
            return _createImage(src, x, y, w, h, transform);
    }
    public static Image createImage(int w, int h)
    {
        return __createImage(w, h);
        if (Thread.CurrentThread.Name == Main.mainThreadName)
            return __createImage(w, h);
        else
            return _createImage(w, h);
    }
    public static Image createImage(sbyte[] imageData, int offset, int lenght)
    {
        if (offset + lenght > imageData.Length)
            return null;
        byte[] temp = new byte[lenght];

        for (int i = 0; i < lenght; i++)
            temp[i] = convertSbyteToByte(imageData[i + offset]);

        return createImage(temp);

    }
    public static byte convertSbyteToByte(sbyte var)
    {
        if (var > 0)
            return (byte)var;

        return (byte)(var + 256);
    }
    public static byte[] convertArrSbyteToArrByte(sbyte[] var)
    {
        byte[] temp = new byte[var.Length];
        for (int i = 0; i < var.Length; i++)
        {
            if (var[i] > 0)
                temp[i] = (byte)var[i];

            else temp[i] = (byte)(var[i] + 256);
        }

        return temp;
    }
    public static Image createRGBImage(int[] rbg, int w, int h, bool bl)
    {
        Image temp = Image.createImage(w, h);
        Color[] t = new Color[rbg.Length];
        for (int i = 0; i < t.Length; i++)
            t[i] = setColorFromRBG(rbg[i]);
        temp.texture.SetPixels(0, 0, w, h, t);
        temp.texture.Apply();
        return temp;
    }
    public static Color setColorFromRBG(int rgb)
    {
        int blue = rgb & 0xFF;
        int green = (rgb >> 8) & 0xFF;
        int red = (rgb >> 16) & 0xFF;
        float b = (float)blue / 256;
        float g = (float)green / 256;
        float r = (float)red / 256;
        Color cl = new Color(r, g, b);
        return cl;
    }
    public static void update()
    {
        if (status == 2)
        {
            status = 1;
            imgTemp = __createEmptyImage();
            status = 0;
        }
        else if (status == 3)
        {
            status = 1;
            imgTemp = __createImage(filenametemp);
            status = 0;
        }
        else if (status == 4)
        {
            status = 1;
            imgTemp = __createImage(datatemp);
            status = 0;
        }
        else if (status == 5)
        {
            status = 1;
            imgTemp = __createImage(imgSrcTemp, xtemp, ytemp, wtemp, htemp, transformtemp);
            status = 0;
        }
        else if (status == 6)
        {
            status = 1;
            imgTemp = __createImage(wtemp, htemp);
            status = 0;
        }
    }
    private static Image _createEmptyImage()
    {
        if (status != 0)
        {
            Debug.LogError("CANNOT CREATE EMPTY IMAGE WHEN CREATING OTHER IMAGE");
            return null;
        }
        imgTemp = null;
        status = 2;
        int i = 0;
        while (i < MAXTIME)
        {
            Thread.Sleep(INTERVAL);
            if (status == 0) break; // create done
            i++;
        }
        if (i == MAXTIME)
        {
            Debug.LogError("TOO LONG FOR CREATE EMPTY IMAGE");
            status = 0;
        }
        //else Debug.Log("Create Empty Image done in "+(i*INTERVAL)+"ms");
        return imgTemp;
    }
    private static Image _createImage(string filename)
    {
        if (status != 0)
        {
            Debug.LogError("CANNOT CREATE IMAGE " + filename + " WHEN CREATING OTHER IMAGE");
            return null;
        }
        imgTemp = null;
        filenametemp = filename;
        status = 3;
        int i = 0;
        while (i < MAXTIME)
        {
            Thread.Sleep(INTERVAL);
            if (status == 0) break; // create done
            i++;
        }
        if (i == MAXTIME)
        {
            Debug.LogError("TOO LONG FOR CREATE IMAGE " + filename);
            status = 0;
        }
        //else Debug.Log("Create Image "+ filename+" done in "+(i*INTERVAL)+"ms");
        return imgTemp;
    }

    private static Image _createImage(byte[] imageData)
    {
        if (status != 0)
        {
            Debug.LogError("CANNOT CREATE IMAGE(FromArray) WHEN CREATING OTHER IMAGE");
            return null;
        }
        imgTemp = null;
        datatemp = imageData;
        status = 4;
        int i = 0;
        while (i < MAXTIME)
        {
            Thread.Sleep(INTERVAL);
            if (status == 0) break; // create done
            i++;
        }
        if (i == MAXTIME)
        {
            Debug.LogError("TOO LONG FOR CREATE IMAGE(FromArray)");
            status = 0;
        }
        //else Debug.Log("Create Image(FromArray) done in "+(i*INTERVAL)+"ms");
        return imgTemp;
    }
    private static Image _createImage(Image src, int x, int y, int w, int h, int transform)
    {
        if (status != 0)
        {
            Debug.LogError("CANNOT CREATE IMAGE(FromSrcPart) WHEN CREATING OTHER IMAGE");
            return null;
        }
        imgTemp = null;
        imgSrcTemp = src;
        xtemp = x;
        ytemp = y;
        wtemp = w;
        htemp = h;
        transformtemp = transform;
        status = 5;
        int i = 0;
        while (i < MAXTIME)
        {
            Thread.Sleep(INTERVAL);
            if (status == 0) break; // create done
            i++;
        }
        if (i == MAXTIME)
        {
            Debug.LogError("TOO LONG FOR CREATE IMAGE(FromSrcPart)");
            status = 0;
        }
        //else Debug.Log("Create Image(FromSrcPart) done in "+(i*INTERVAL)+"ms");
        return imgTemp;
    }
    private static Image _createImage(int w, int h)
    {
        if (status != 0)
        {
            Debug.LogError("CANNOT CREATE IMAGE(w,h) WHEN CREATING OTHER IMAGE");
            return null;
        }
        imgTemp = null;
        wtemp = w;
        htemp = h;
        status = 6;
        int i = 0;
        while (i < MAXTIME)
        {
            Thread.Sleep(INTERVAL);
            if (status == 0) break; // create done
            i++;
        }
        if (i == MAXTIME)
        {
            Debug.LogError("TOO LONG FOR CREATE IMAGE(w,h)");
            status = 0;
        }
        //else Debug.Log("Create Image(w,h) done in " + (i * INTERVAL) + "ms");
        return imgTemp;
    }

    private static Image __createImage(string filename)
    {
        //Debug.Log("CREATE IMAGE FROM FILE: "+filename);
        //Image img=new Image();
        Image img = new Image();
        //TextAsset imageasset = (TextAsset)Resources.Load(filename ,typeof(TextAsset));
        Texture2D t = Resources.Load(filename) as Texture2D;

        //if(imageasset==null||imageasset.bytes==null||imageasset.bytes.Length==0)
        if (t == null)
        {
            Debug.LogError("Create Image " + filename + " fail");
            return null;
        }
        //img.texture.LoadImage(imageasset.bytes);
        img.texture = t;
        img.w = img.texture.width;
        img.h = img.texture.height;
        setTextureQuality(img);
        // Out.println("load img thanh cong >> "+filename);
        return img;
    }
    private static Image __createImage(byte[] imageData)
    {
        //Debug.Log("CREATE IMAGE FROM BYTE[]: size="+imageData.Length);
        if (imageData == null || imageData.Length == 0)
        {
            Debug.LogError("Create Image from byte array fail");
            return null;
        }
        Image img = new Image();
        try
        {
            img.texture.LoadImage(imageData);
            img.w = img.texture.width;
            img.h = img.texture.height;
            setTextureQuality(img);
        }
        catch (Exception e)
        {
            Debug.LogError("CREAT IMAGE FROM ARRAY FAIL \n" + Environment.StackTrace);
        }
        return img;
    }
    private static Image __createImage(Image src, int x, int y, int w, int h, int transform)
    {
        Image img = new Image();
        img.texture = new Texture2D(w, h);
        y = src.texture.height - y - h;
        for (int i = 0; i < w; i++)
            for (int j = 0; j < h; j++)
            {
                int ii = i;
                if (transform == 2) ii = w - i;
                int jj = j;
                img.texture.SetPixel(i, j, src.texture.GetPixel(x + ii, y + jj));
            }
        img.texture.Apply();
        img.w = img.texture.width;
        img.h = img.texture.height;
        setTextureQuality(img);
        return img;
    }
    private static Image __createEmptyImage()
    {
        return new Image();
    }
    public static Image __createImage(int w, int h)
    {
        Image img = new Image();
        img.texture = new Texture2D(w, h);
        setTextureQuality(img);
        img.w = w;
        img.h = h;
        return img;
    }
    public static int getImageWidth(Image image)
    {
        return image.getWidth();
    }
    public static int getImageHeight(Image image)
    {
        return image.getHeight();
    }
    public int getWidth()
    {
        return w / mGraphics.zoomLevel;
    }
    public int getHeight()
    {
        return h / mGraphics.zoomLevel;
    }

    private static void setTextureQuality(Image img)
    {
        setTextureQuality(img.texture);
    }
    private static void setTextureQuality(Texture2D texture)
    {
        texture.anisoLevel = 0;
        texture.filterMode = FilterMode.Point;
        texture.mipMapBias = 0;
        texture.wrapMode = TextureWrapMode.Clamp;
    }
}
